package com.gitee.feizns.convert.method.valueof;

import com.gitee.feizns.convert.method.AbstractMethodConverter;
import com.gitee.feizns.convert.method.MethodSelectionStrategyList;
import com.gitee.feizns.convert.method.MethodWrapper;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.stream.Stream;

/**
 * @author feizns
 * @since 2019/5/28
 */
public abstract class AbstractValueOfMethodConverter extends AbstractMethodConverter {

    /**
     * 方法名称
     */
    public static final String METHOD_NAME = "valueOf";

    /**
     * 过滤方法
     * @param methodStream
     * @return
     */
    protected abstract Stream<Method> filterMethod(Stream<Method> methodStream);

    /**
     * 方法选择策略
     * @return
     */
    protected abstract MethodSelectionStrategyList getSelectionStrategy(Class<?> targetType);

    @Override
    public Object to(Object original, Class targetType) {
        Method[] methods = filterMethod(defaultFilter(targetType)).toArray(Method[]::new);
        MethodWrapper methodWrapper = getSelectionStrategy(targetType).find(targetType, original, methods);
        return methodWrapper != null ? methodWrapper.invoke() : null;
    }

    /**
     *
     * @param targetType
     * @return
     */
    private static final Stream<Method> defaultFilter(Class<?> targetType) {
        return Arrays.stream(targetType.getMethods())
                .filter(method -> METHOD_NAME.equals(method.getName()))
                .filter(method -> Modifier.isStatic(method.getModifiers()))
                .filter(method -> method.getReturnType().isAssignableFrom(targetType));
    }

}
